package cn.ellacat.game.guess;

import java.util.Collections;
import java.util.List;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import static cn.ellacat.game.guess.Constants.CARD_STACK;
import static cn.ellacat.game.guess.Constants.INIT_HAND_CARD_STACK;

/**
 * @author wjc133
 */
@Slf4j
public class Player {
    private final List<Card> cards = Lists.newArrayList();
    private final IoWrapper ioWrapper = IoWrapper.getInstance();

    private String nickname;

    public String getNickname() {
        return this.nickname;
    }

    public void setNickname(final String nickname) {
        this.nickname = nickname;
    }

    public List<Card> getCards() {
        return this.cards;
    }

    public boolean hasHiddenCard() {
        for (final Card card : this.cards) {
            if (card.isHidden()) {
                return true;
            }
        }
        return false;
    }

    public void round(final List<Card> deck, final List<Card> sideHand) {
        final Card card = this.draw(deck);
        this.cards.add(card);
        if (card.getType() == CardType.UNIVERSAL) {
            // 指定万能牌指代的值，当前版本不支持修改
            this.setUniversalNum(card);
        }
        Collections.sort(this.cards);
        if (this.cards.size() <= INIT_HAND_CARD_STACK) {
            return;
        }
        do {
            if (!this.guess(sideHand)) {
                card.setHidden(false);
                break;
            }
        } while (this.wantContinueGuess());
    }

    private boolean wantContinueGuess() {
        this.ioWrapper.outLine("希望继续猜吗？[y/N]");
        final String answer = this.ioWrapper.inString();
        return "y".equalsIgnoreCase(answer);
    }

    private boolean guess(final List<Card> sideHand) {
        this.ioWrapper.outString("对方手牌:  ");
        for (int i = 0; i < sideHand.size(); i++) {
            final Card card = sideHand.get(i);
            this.ioWrapper.outString(i + "-" + card.getColor() + (card.isHidden() ? "" : ":" + card.getType() + ":" + card.getNumber()) + " ");
        }
        this.ioWrapper.outLine();
        this.ioWrapper.outLine("----------------------------");
        this.ioWrapper.outString("你的手牌:  ");
        for (int i = 0; i < this.cards.size(); i++) {
            final Card card = this.cards.get(i);
            this.ioWrapper.outString(i + "-" + card.getColor() + ":" + card.getType() + ":" + card.getNumber() + " ");
        }
        this.ioWrapper.outLine();

        // 猜
        this.ioWrapper.outLine("猜吧~ 格式：[序号] [猜值]");
        final int index = this.ioWrapper.inInt();
        final int answer = this.ioWrapper.inInt();
        final Card guessCard = sideHand.get(index);
        final boolean result = answer == guessCard.getNumber();
        if (result) {
            guessCard.setHidden(false);
        }
        return result;
    }

    private void setUniversalNum(final Card card) {
        this.ioWrapper.outLine("请" + this.getNickname() + "指定万能牌代替的牌大小：");
        final int answer = this.ioWrapper.inInt();
        if (answer < 0 || answer > CARD_STACK) {
            this.ioWrapper.outLine("无效输入！");
            return;
        }
        card.setNumber(answer);
    }

    private Card draw(final List<Card> deck) {
        this.ioWrapper.outLine("请" + this.getNickname() + "抽牌（输入序号）:");
        for (int i = 0; i < deck.size(); i++) {
            final Card card = deck.get(i);
            final CardColor color = card.getColor();
            final ConsoleColorUtils.Color c = CardColor.YELLOW == color ? ConsoleColorUtils.Color.YELLOW : ConsoleColorUtils.Color.BLUE;
            this.ioWrapper.outLine("序号" + i + " " + "颜色:" + ConsoleColorUtils.getConsoleStr(color.toString(), ConsoleColorUtils.Style.BOLD, c));
        }
        final int i = this.ioWrapper.inInt();
        if (i < 0 || i >= deck.size()) {
            this.ioWrapper.outLine("无效输入！");
            return null;
        }
        final Card card = deck.remove(i);
        this.ioWrapper.outLine("你抽到了:" + card);
        return card;
    }

    public boolean hasCard() {
        return CollectionUtils.isNotEmpty(this.cards);
    }
}
